<?php defined('SYSPATH') or die('No direct script access.');
/**
 * 扩展并重写 DB 类
 *
 * @author  Yellow.Chow <aultoale@gmail.com>
 * @version $Id: db.php 119 2012-03-29 10:22:26Z yellow.chow $
 * @license http://www.gnu.org/licenses/gpl-3.0.html    GPL 3
 */

/**
 * Provides a shortcut to get Database related objects for [making queries](../database/query).
 *
 * Shortcut     | Returned Object
 * -------------|---------------
 * [`DB::query()`](#query)   | [Database_Query]
 * [`DB::insert()`](#insert) | [Database_Query_Builder_Insert]
 * [`DB::insert()`](#insert) | [Database_Query_Builder_Replace]
 * [`DB::select()`](#select),<br />[`DB::select_array()`](#select_array) | [Database_Query_Builder_Select]
 * [`DB::update()`](#update) | [Database_Query_Builder_Update]
 * [`DB::delete()`](#delete) | [Database_Query_Builder_Delete]
 * [`DB::expr()`](#expr)     | [Database_Expression]
 *
 * You pass the same parameters to these functions as you pass to the objects they return.
 *
 * @package    Kohana/Database
 * @category   Base
 * @author     Kohana Team
 * @copyright  (c) 2009 Kohana Team
 * @license    http://kohanaphp.com/license
 */
class DB {

    /**
     * @var Kohana_Config
     */
    public static $config = NULL;

    /**
     * Create a new Database_Iterator instance
     *
     * @param  Database_Query_Builder_Select  $select
     * @param  string  $db
     * @param  int     $step
     * @return Database_Iterator
     */
    public static function iterator(Database_Query_Builder_Select $select, $db = NULL, $step = NULL)
    {
        return new Database_Iterator($select, $db, $step);
    }

    /**
     * Create a new [Database_Query] of the given type.
     *
     *     // Create a new SELECT query
     *     $query = DB::query(Database::SELECT, 'SELECT * FROM users');
     *
     *     // Create a new DELETE query
     *     $query = DB::query(Database::DELETE, 'DELETE FROM users WHERE id = 5');
     *
     * Specifying the type changes the returned result. When using
     * `Database::SELECT`, a [Database_Query_Result] will be returned.
     * `Database::INSERT` queries will return the insert id and number of rows.
     * For all other queries, the number of affected rows is returned.
     *
     * @param   integer  type: Database::SELECT, Database::UPDATE, etc
     * @param   string   SQL statement
     * @return  Database_Query
     */
    public static function query($type, $sql)
    {
        return new Database_Query($type, $sql);
    }

    /**
     * Create a new [Database_Query_Builder_Select]. Each argument will be
     * treated as a column. To generate a `foo AS bar` alias, use an array.
     *
     *     // SELECT id, username
     *     $query = DB::select('id', 'username');
     *
     *     // SELECT id AS user_id
     *     $query = DB::select(array('id', 'user_id'));
     *
     * @param   mixed   column name or array($column, $alias) or object
     * @param   ...
     * @return  Database_Query_Builder_Select
     */
    public static function select($columns = NULL)
    {
        return new Database_Query_Builder_Select(func_get_args());
    }

    /**
     * Create a new [Database_Query_Builder_Select] from an array of columns.
     *
     *     // SELECT id, username
     *     $query = DB::select_array(array('id', 'username'));
     *
     * @param   array   columns to select
     * @return  Database_Query_Builder_Select
     */
    public static function select_array(array $columns = NULL)
    {
        return new Database_Query_Builder_Select($columns);
    }

    /**
     * Create a new [Database_Query_Builder_Insert].
     *
     *     // INSERT INTO users (id, username) VALUES (1, jason)
     *     $query = DB::insert('users', array('id' => 1, 'username' => 'jason'));
     *     $query = DB::insert('users', array(array('id' => 1, 'username' => 'jason'), ...));
     *
     * @param   string  table to insert into
     * @param   array   data or multiple data of replace
     * @return  Database_Query_Builder_Insert
     */
    public static function insert($table, array $data)
    {
        if (is_array(current($data)) OR ( ! is_numeric(key($data)) AND array_keys($data) != array_values($data)))
        {
            $columns = array_keys(is_array(current($data)) ? current($data) : $data);
            $insert = new Database_Query_Builder_Insert($table, $columns);
            return $insert->values($data);
        }
        else // Compatible with the old method
        {
            return  new Database_Query_Builder_Insert($table, $data);
        }
    }

    /**
     * Create a new [Database_Query_Builder_Replace].
     *
     *     // REPLACE INTO users (id, username) VALUES (1, jason)
     *     $query = DB::replace('users', array('id' => 1, 'username' => 'jason'));
     *     $query = DB::replace('users', array(array('id' => 1, 'username' => 'jason'), ...));
     *
     * @param   string  table to replace
     * @param   array   data of replace
     * @return  Database_Query_Builder_Replace
     */
    public static function replace($table, array $data)
    {
        if (is_array(current($data)) OR ( ! is_numeric(key($data)) AND array_keys($data) != array_values($data)))
        {
            $columns = array_keys(is_array(current($data)) ? current($data) : $data);
            $insert = new Database_Query_Builder_Replace($table, $columns);
            return $insert->values($data);
        }
        else // Compatible with the old method
        {
            return  new Database_Query_Builder_Replace($table, $data);
        }
    }

    /**
     * Create a new [Database_Query_Builder_Update].
     *
     *     // UPDATE users SET username = jason ...
     *     $query = DB::update('users', array('username' => 'jason', ...));
     *
     * @param   string  table to update
     * @param   array   data of update
     * @return  Database_Query_Builder_Update
     */
    public static function update($table = NULL, array $data = NULL)
    {
        $update = new Database_Query_Builder_Update($table);
        if ($data)
        {
            $update->set($data);
        }
        return $update;
    }

    /**
     * Create a new [Database_Query_Builder_Delete].
     *
     *     // DELETE FROM users
     *     $query = DB::delete('users');
     *
     * @param   string  table to delete from
     * @return  Database_Query_Builder_Delete
     */
    public static function delete($table = NULL)
    {
        return new Database_Query_Builder_Delete($table);
    }

    /**
     * Create a new [Database_Expression] which is not escaped. An expression
     * is the only way to use SQL functions within query builders.
     *
     *     $expression = DB::expr('COUNT(users.id)');
     *     $query = DB::update('users')->set(array('login_count' => DB::expr('login_count + 1')))->where('id', '=', $id);
     *     $users = ORM::factory('user')->where(DB::expr("BINARY `hash`"), '=', $hash)->find();
     *
     * @param   string  expression
     * @param   array   parameters
     * @return  Database_Expression
     */
    public static function expr($string, $parameters = array())
    {
        return new Database_Expression($string, $parameters);
    }

} // End DB